package cc.sends;

import java.util.ArrayList;
import java.util.List;

/**
 * @ Description : OPI Algorithm
 * @ Author : ChristosC
 * @ Date : 2020/12/15 17:14
 */
public class Optimal {
    private int ramSize;
    private int requestPageQueueSize;
    private int missTime = 0;
    private float missRate = 0f;
    private List<Page> ramQueue;
    private List<Page> requestPageQueue;

    public void init(List<Page> requestPageQueue, int ramSize, int requestPageQueueSize){
        this.requestPageQueueSize = requestPageQueueSize;
        this.ramSize = ramSize;
        this.ramQueue = new ArrayList();
        this.requestPageQueue = requestPageQueue;
    }

    public void start(){
        Page currPage;
        Page lastWillUsePage;
        Page lastWillUsePageInRam;
        int lastWillUsePageIndexInRam;
        int currIndex;
        int maxIndex;
        int outPageNum;

        do{
            outPageNum = -1;
            // 取出队头
            currPage = requestPageQueue.get(0);
            // 若 currPage 不在 ramQueue 中
            if(!ramQueueContains(currPage)){
                // 内存块满,主要置换逻辑
                if(ramQueueFull()){
                    missTime++;
                    maxIndex = 0;
                    // 对ramQueue中的每一个page
                    for(Page page : ramQueue){
                        currIndex = 0;

                        // ...与requestPageQueue中的每一个page进行对比
                        for(Page page1 : requestPageQueue){
                            // 找到第一 num 相同的page 后跳出循环
                            if(page.getNum() == page1.getNum()){
                                break;
                            }
                            currIndex++;
                        }
                        if(currIndex >= requestPageQueue.size()){
                            currIndex=0;
                            outPageNum = page.getNum();
                        }
                        maxIndex = (currIndex>maxIndex)?currIndex:maxIndex;
                    }
                    if(outPageNum == -1){
                        // 从requestPageQueue 中获取 ramQueue 中最后会调用的 page
                        lastWillUsePage = requestPageQueue.get(maxIndex);
                    }else {
                        lastWillUsePage = new Page(outPageNum);
                    }
                    // 获取该page 在ramQueue 中的位置
                    lastWillUsePageIndexInRam = getLastWillUsePageIndexInRam(lastWillUsePage);
                    // 替换 ramQueue 上的对应 Page
                    lastWillUsePageInRam = ramQueue.get(lastWillUsePageIndexInRam);
                    System.out.print("替换"+lastWillUsePageInRam.getNum()+"后：");
                    lastWillUsePageInRam.setNum(currPage.getNum());

                    for(Page page : ramQueue){
                        System.out.print(page.getNum()+" ");
                    }
                    System.out.println();
                }
                else {
                    // 内存块未满直接加入内存块
                    ramQueue.add(currPage);
                    System.out.print("直接加入：");
                    for(Page page : ramQueue){
                        System.out.print(page.getNum()+" ");
                    }
                    System.out.println();
                }
            }
            // 去除队头
            requestPageQueue.remove(0);
        }while (requestPageQueue.size()>0);
        System.out.println("缺页数："+missTime);
        missRate = (float)missTime/requestPageQueueSize;
        System.out.println("缺页率："+missRate);
    }

    private boolean ramQueueFull(){
        return ramQueue.size() == ramSize;
    }
    private int getLastWillUsePageIndexInRam(Page lastWillUsePage){
        int result = 0;
        int i = 0;
        for(Page page : ramQueue){
            if(page.getNum() == lastWillUsePage.getNum()){
                result = i;
                break;
            }
            i++;
        }
        return result;
    }
    private boolean ramQueueContains(Page currPage){
        boolean result = false;
        for(Page page : ramQueue){
            if(currPage.getNum() == page.getNum()){
                result = true;
            }
        }
        return result;
    }
}
